import store from '@/store';
import { api } from '@/lib/api';
import { getStorage } from '@/lib/utils';
import { KEY_AUTH_TOKEN, LOGIN_STATUS } from '@/lib/constant';
import { decodeJwtPayload } from './crypto';

let loginPromise: Promise<string | boolean> | null = null;

/**
 * 登录流程
 * @return {boolean} 登录是否成功
 */
export function login(ignore = false): Promise<string | boolean> {
    if (loginPromise) {
        return loginPromise;
    }

    loginPromise = new Promise<string | boolean>(async (resolve) => {
        function resolveAndClean(tokenOrFlag?: string | boolean) {
            resolve(tokenOrFlag);
            loginPromise = null;
        }

        if (!ignore) {
            let parsedJwt: any = null;
            const jwt = await getStorage(KEY_AUTH_TOKEN);
            if (jwt) {
                parsedJwt = decodeJwtPayload(jwt);
            }
            // 解析成功 并且 没有过期
            if (parsedJwt && Date.now() < parsedJwt.exp * 1000) {
                store.commit('auth/setLogin', LOGIN_STATUS.LOGINED);
            }
        }

        // 当前已经登录
        const hasLogin = store.state.auth.hasLogin;
        /* eslint-disable handle-callback-err */
        const session = await api.checkSession().then(() => true).catch(err => false);
        if (session && (hasLogin === LOGIN_STATUS.LOGINING || hasLogin === LOGIN_STATUS.LOGINED)) {
            resolveAndClean(true);
            return;
        }
        store.commit('auth/setLogin', LOGIN_STATUS.LOGINING);
        const loginRes = await api.login();
        const res = await store.dispatch('auth/login', {
            code: loginRes.code,
        });
        if (res.statusCode === 200) {
            store.commit('auth/setLogin', LOGIN_STATUS.LOGINED);
            const data = res.data.data;
            resolveAndClean(data ? data.token : true);
        } else {
            wx.showToast({
                title: res.data.message,
                icon: 'none',
            });
            console.log('登录失败！');
            resolveAndClean(false);
        }
    });
    return loginPromise;
}
